﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Ink;
using ClassRoom.Packets;
using ClassRoom.ViewModels;
using ClassRoom.Commands;

namespace ClassRoom.Views
{
    public partial class ClassRoomView : UserControl
    {
        #region FIELDS

        private Stroke _stroke = null;
        private Stroke _networkStroke = null;
        private StylusPointCollection _networkEraserPoints;
        private StylusPointCollection _eraserPoints;
        private InkMode _inkMode = InkMode.Draw;

        #endregion

        public enum InkMode
        { 
            Draw,
            Erase
        }

        #region CONSTRUCTORS

        public ClassRoomView()
        {
            InitializeComponent();

            this.DataContext = new ClassRoomViewModel(this);
        }         

        #endregion

        private void txtMessage_KeyDown(object sender, KeyEventArgs e)
        {            
            if (e.Key == Key.Enter)
            {
                ((ClassRoomViewModel)this.DataContext).ChatMessage = this.txtMessage.Text;
                ((ClassRoomViewModel)this.DataContext).ExecuteSendCommand(null);
            }
        }

        #region BLACKBOARD

        private void BlackBoard_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.BlackBoard.CaptureMouse();
            if (_inkMode == InkMode.Draw)
            {
                _stroke = new Stroke();
                _stroke.DrawingAttributes.Color = this.ColorPicker.SelectedColor;
                StylusPointCollection stylusPointCollection = e.StylusDevice.GetStylusPoints(this.BlackBoard);
                _stroke.StylusPoints.Add(stylusPointCollection);
                BlackBoard.Strokes.Add(_stroke);

                #region Send blackboard packet
                List<double> xCoordinateCollection = new List<double>();
                List<double> yCoordinateCollection = new List<double>();
                for(int i = 0; i < stylusPointCollection.Count; i++)
                {
                    xCoordinateCollection.Add(stylusPointCollection[i].X);
                    yCoordinateCollection.Add(stylusPointCollection[i].Y);
                }

                Packets.BlackBoard blackBoard = new Packets.BlackBoard(Packets.BlackBoardAction.Draw, _stroke.DrawingAttributes.Color, xCoordinateCollection, yCoordinateCollection);
                ((ClassRoomViewModel)this.DataContext)._Network.Send(blackBoard, ObjectType.BlackBoard);
                #endregion
            }
            else if (_inkMode == InkMode.Erase)
            {
                _eraserPoints = new StylusPointCollection();
                StylusPointCollection stylusPointCollection = e.StylusDevice.GetStylusPoints(this.BlackBoard);
                _eraserPoints = stylusPointCollection;
                StrokeCollection hits = this.BlackBoard.Strokes.HitTest(_eraserPoints);
                for (int i = 0; i < hits.Count; i++)
                {
                    this.BlackBoard.Strokes.Remove(hits[i]);
                }

                #region Send blackboard packet
                List<double> xCoordinateCollection = new List<double>();
                List<double> yCoordinateCollection = new List<double>();
                for (int i = 0; i < stylusPointCollection.Count; i++)
                {
                    xCoordinateCollection.Add(stylusPointCollection[i].X);
                    yCoordinateCollection.Add(stylusPointCollection[i].Y);
                }

                Packets.BlackBoard blackBoard = new Packets.BlackBoard(Packets.BlackBoardAction.Erase, xCoordinateCollection, yCoordinateCollection);
                ((ClassRoomViewModel)this.DataContext)._Network.Send(blackBoard, ObjectType.BlackBoard);
                #endregion
            }
        }

        private void BlackBoard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _stroke = null;
            _eraserPoints = null;
            this.BlackBoard.ReleaseMouseCapture();
            ((ClassRoomViewModel)this.DataContext)._Network.Send(new Packets.BlackBoard(Packets.BlackBoardAction.MouseUp, null, null), ObjectType.BlackBoard);
        }

        private void BlackBoard_MouseMove(object sender, MouseEventArgs e)
        {
            if (_inkMode == InkMode.Draw)
            {
                if (_stroke != null)
                {
                    StylusPointCollection stylusPointCollection = e.StylusDevice.GetStylusPoints(this.BlackBoard);
                    for (int i = 0; i < stylusPointCollection.Count; i++)
                    {
                        if (stylusPointCollection[i].X < 0 || stylusPointCollection[i].X > this.BlackBoard.Width
                            || stylusPointCollection[i].Y < 0 || stylusPointCollection[i].Y > this.BlackBoard.Height)
                        {
                            this.BlackBoard_MouseLeftButtonUp(null, null);
                            return;
                        }
                        else
                        {
                            _stroke.StylusPoints.Add(stylusPointCollection[i]);
                        }
                    }

                    #region Send blackboard packet
                    List<double> xCoordinateCollection = new List<double>();
                    List<double> yCoordinateCollection = new List<double>();
                    for (int i = 0; i < stylusPointCollection.Count; i++)
                    {
                        xCoordinateCollection.Add(stylusPointCollection[i].X);
                        yCoordinateCollection.Add(stylusPointCollection[i].Y);
                    }

                    Packets.BlackBoard blackBoard = new Packets.BlackBoard(Packets.BlackBoardAction.Draw, _stroke.DrawingAttributes.Color, xCoordinateCollection, yCoordinateCollection);
                    ((ClassRoomViewModel)this.DataContext)._Network.Send(blackBoard, ObjectType.BlackBoard);
                    #endregion
                }
            }
            else if (_inkMode == InkMode.Erase)
            {
                if (null != _eraserPoints)
                {
                    StylusPointCollection stylusPointCollectionSend = new StylusPointCollection();
                    StylusPointCollection stylusPointCollection = e.StylusDevice.GetStylusPoints(this.BlackBoard);                    
                    _eraserPoints.Add(stylusPointCollection);
                    StrokeCollection hits = this.BlackBoard.Strokes.HitTest(_eraserPoints);
                    for (int i = 0; i < hits.Count; i++)
                    {
                        this.BlackBoard.Strokes.Remove(hits[i]);
                        stylusPointCollectionSend.Add(hits[i].StylusPoints);
                    }

                    #region Send blackboard packet
                    List<double> xCoordinateCollection = new List<double>();
                    List<double> yCoordinateCollection = new List<double>();
                    for (int i = 0; i < stylusPointCollectionSend.Count; i++)
                    {
                        xCoordinateCollection.Add(stylusPointCollectionSend[i].X);
                        yCoordinateCollection.Add(stylusPointCollectionSend[i].Y);
                    }

                    Packets.BlackBoard blackBoard = new Packets.BlackBoard(Packets.BlackBoardAction.Erase, xCoordinateCollection, yCoordinateCollection);
                    ((ClassRoomViewModel)this.DataContext)._Network.Send(blackBoard, ObjectType.BlackBoard);
                    #endregion
                }
            }
        }

        private void PenImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this._inkMode = InkMode.Draw;
            this.BlackBoard.Cursor = Cursors.Stylus;
            this.PenImage.Opacity = 1.0;
            this.ErasorImage.Opacity = 0.5;
        }

        private void ErasorImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this._inkMode = InkMode.Erase;
            this.BlackBoard.Cursor = Cursors.Eraser;
            this.ErasorImage.Opacity = 1.0;
            this.PenImage.Opacity = 0.5;
        }

        public void ExecuteBlackBoardPacket(Packets.BlackBoard bb)
        {
            StylusPointCollection stylusPointCollection;
            switch(bb.BlackBoardAction)
            {
                case Packets.BlackBoardAction.MouseUp:
                    _networkStroke = null;
                    _networkEraserPoints = null;

                    break;
                case Packets.BlackBoardAction.Draw:
                    stylusPointCollection = new StylusPointCollection();
                    for (int i = 0; i < bb.XCoordinateCollection.Count; i++)
                    {
                        stylusPointCollection.Add(new StylusPoint(bb.XCoordinateCollection[i], bb.YCoordinateCollection[i]));
                    }

                    if (_networkStroke == null)
                    {
                        _networkStroke = new Stroke();
                        _networkStroke.DrawingAttributes.Color = bb.Color;
                        _networkStroke.StylusPoints.Add(stylusPointCollection);
                        this.BlackBoard.Strokes.Add(_networkStroke);
                    }
                    else
                    {
                        _networkStroke.StylusPoints.Add(stylusPointCollection);
                    }

                    break;
                case Packets.BlackBoardAction.Erase:
                    stylusPointCollection = new StylusPointCollection();
                    for (int i = 0; i < bb.XCoordinateCollection.Count; i++)
                    {
                        stylusPointCollection.Add(new StylusPoint(bb.XCoordinateCollection[i], bb.YCoordinateCollection[i]));
                    }

                    _networkEraserPoints = new StylusPointCollection();
                    _networkEraserPoints = stylusPointCollection;
                    StrokeCollection hits = this.BlackBoard.Strokes.HitTest(_networkEraserPoints);
                    for (int i = 0; i < hits.Count; i++)
                    {
                        this.BlackBoard.Strokes.Remove(hits[i]);
                    }

                    break;
            }
        }

        #endregion

        #region SLIDE

        private void imgOpenPPT_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Multiselect = false;
            openFileDialog.Filter = "Powerpoint (*.ppt, *.pptx) | *.ppt; *.pptx";
            FullSlide fullSlide = new FullSlide();
            if (openFileDialog.ShowDialog().Value)
            {
                using (FileStream fs = openFileDialog.File.OpenRead())
                {
                    ((ClassRoomViewModel)this.DataContext).StopSendWebcam();
                    byte[] buffer = new byte[fs.Length];
                    fs.Read(buffer, 0, buffer.Length);
                    fullSlide.Buffer = buffer;
                    fullSlide.FileType = openFileDialog.File.Extension;
                    ((ClassRoomViewModel)this.DataContext)._Network.Send(fullSlide, ObjectType.FullSlide);
                }                
            }
        }

        private void imgNextPPTSlide_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ClassRoomViewModel viewModel = (ClassRoomViewModel)this.DataContext;
            if(viewModel.CurrentPPTSlideNo < viewModel.TotalPPTSlides)
            {
                viewModel.CurrentPPTSlideNo++;
                viewModel._Network.Send(viewModel.CurrentPPTSlideNo, ObjectType.OneSlide);
            }
        }

        private void imgPrevPPTSlide_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ClassRoomViewModel viewModel = (ClassRoomViewModel)this.DataContext;
            if (viewModel.CurrentPPTSlideNo > 1)
            {
                viewModel.CurrentPPTSlideNo--;
                viewModel._Network.Send(viewModel.CurrentPPTSlideNo, ObjectType.OneSlide);
            }
        }

        #endregion                
    }
}
